Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add precheck for receivers account in sendRawTransactionCheck #3310

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

nadezhdapopovaa
Copy link
Contributor

Description:
Added precheck for receiver's account in sendRawTransactionCheck

Fixes #3286

Copy link

github-actions bot commented Dec 5, 2024

Test Results

 22 files  +  2  306 suites  +31   58m 58s ⏱️ + 15m 20s
614 tests +  1  604 ✅  -   1  4 💤 ±0  6 ❌ +2 
802 runs  +107  790 ✅ +103  6 💤 +2  6 ❌ +2 

For more details on these failures, see this check.

Results for commit 3b85b1a. ± Comparison against base commit b5e747f.

This pull request removes 3 and adds 4 tests. Note that renamed tests count towards both.
"after each" hook for "@release captures transfer events" ‑ RPC Server Acceptance Tests Acceptance tests @web-socket-batch-3 eth_subscribe "after each" hook for "@release captures transfer events"
"before all" hook for "Subscribes for debug" ‑ RPC Server Acceptance Tests Acceptance tests @web-socket-batch-3 eth_subscribe Subscribes to log events "before all" hook for "Subscribes for debug"
"before each" hook for "@release captures transfer events" ‑ RPC Server Acceptance Tests Acceptance tests @web-socket-batch-3 eth_subscribe "before each" hook for "@release captures transfer events"
"before all" hook for "should execute "eth_getCode" for hts token" ‑ RPC Server Acceptance Tests Acceptance tests @api-batch-2 RPC Server Acceptance Tests eth_getCode "before all" hook for "should execute "eth_getCode" for hts token"
"before each" hook for "should execute "eth_getStorageAt" request to get current state changes" ‑ RPC Server Acceptance Tests Acceptance tests @api-batch-2 RPC Server Acceptance Tests "before each" hook for "should execute "eth_getStorageAt" request to get current state changes"
"before each" hook: reducing balance for "reverts" ‑ RPC Server Acceptance Tests Acceptance tests @erc20 Acceptance Tests HTS token should behave like erc20 transfer from when the token owner is not the zero address when the recipient is not the zero address when the spender does not have enough allowance when the token owner does not have enough balance "before each" hook: reducing balance for "reverts"
should fail "eth_sendRawTransaction" if receiver's account has receiver_sig_required enabled ‑ RPC Server Acceptance Tests Acceptance tests @api-batch-1 RPC Server Acceptance Tests RPC Server Acceptance Tests Transaction related RPC Calls Prechecks should fail "eth_sendRawTransaction" if receiver's account has receiver_sig_required enabled

♻️ This comment has been updated with latest results.

@nadezhdapopovaa nadezhdapopovaa force-pushed the 3286-add-prechecks-to-the-sendrawtransaction-method-to-verify-the-validity-of-the-receivers-account-address branch from 589773c to 92c28db Compare December 5, 2024 14:56
Copy link

codecov bot commented Dec 5, 2024

Codecov Report

Attention: Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 84.96%. Comparing base (1551da6) to head (92c28db).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
packages/relay/src/lib/precheck.ts 75.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3310      +/-   ##
==========================================
+ Coverage   77.96%   84.96%   +6.99%     
==========================================
  Files          66       69       +3     
  Lines        4475     4641     +166     
  Branches     1003     1043      +40     
==========================================
+ Hits         3489     3943     +454     
+ Misses        612      394     -218     
+ Partials      374      304      -70     
Flag Coverage Δ
config-service 98.14% <ø> (ø)
relay 78.67% <62.50%> (-0.06%) ⬇️
server 83.28% <ø> (ø)
ws-server 36.66% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/relay/src/lib/precheck.ts 87.38% <75.00%> (+13.80%) ⬆️

... and 26 files with indirect coverage changes

Copy link
Member

@quiet-node quiet-node left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Some blocking requests

Comment on lines 89 to 91
if (parsedTx.to) {
await this.receiverAccount(parsedTx, requestDetails);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the parsedTx.to check inside the receiverAccount() precheck instead.

* @param {RequestDetails} requestDetails - The request details for logging and tracking.
*/
async receiverAccount(tx: Transaction, requestDetails: RequestDetails) {
const verifyAccount = await this.mirrorNodeClient.getAccount(tx.to!, requestDetails);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add the parsedTx.to check here. We can make it only run this precheck of parsedTx.to is found so in line 390 we don't have to use the ! operator.

const verifyAccount = await this.mirrorNodeClient.getAccount(tx.to!, requestDetails);

if (verifyAccount !== null && verifyAccount.receiver_sig_required === true) {
throw predefined.INTERNAL_ERROR("Receiver's signature is required.");
Copy link
Member

@quiet-node quiet-node Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm not sure if INTERNAL_ERROR is appropriate here. Looks like other prechecks have their own dedicated predefined errors. Should we follow the pattern and create a dedicated prefined error for receiver account?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, there may be an existing error that could be used but if not add a new one

async receiverAccount(tx: Transaction, requestDetails: RequestDetails) {
const verifyAccount = await this.mirrorNodeClient.getAccount(tx.to!, requestDetails);

if (verifyAccount !== null && verifyAccount.receiver_sig_required === true) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you kindly did some extra research and add a comment here stating why we want to make sure receiver_sig_required attribute is turned off?

* @param {Transaction} tx - The transaction.
* @param {RequestDetails} requestDetails - The request details for logging and tracking.
*/
async receiverAccount(tx: Transaction, requestDetails: RequestDetails) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add test coverage for this method in the precheck.spec.ts


if (verifyAccount !== null && verifyAccount.receiver_sig_required === true) {
throw predefined.INTERNAL_ERROR("Receiver's signature is required.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add another check to see if verifyAccount is null then throw a RESOURCE_NOT_FOUND and include the value of tx.to.

      throw predefined.RESOURCE_NOT_FOUND(`Cannot find receiver account: tx.to=${tx.to}`);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Careful on this one since there are valid cases for tx.to not being set e.g. contract create.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh yeah you're right tx.to is nullable if the transaction is a contract create transaction. Then maybe in the test make the tx.to a non-null address but mock not found. @nadezhdapopovaa please let me know if this is clear enough

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait this block only executes when tx.to is not null; therefore, it is still possible for the mirror node to return a null result if tx.to is not found on the network. I'd suggest instead of checking if (verifyAccount !== null && verifyAccount.receiver_sig_required === true) for the sig required, we can pull the verifyAccount !== null out and add a new block to check the validity of the verifyAccount. If it's null then throw RESOURCE_NOT_FOUND like how we did with the tx.from.

@nadezhdapopovaa nadezhdapopovaa force-pushed the 3286-add-prechecks-to-the-sendrawtransaction-method-to-verify-the-validity-of-the-receivers-account-address branch 2 times, most recently from 66403c6 to 7931099 Compare December 11, 2024 14:39
@nadezhdapopovaa nadezhdapopovaa force-pushed the 3286-add-prechecks-to-the-sendrawtransaction-method-to-verify-the-validity-of-the-receivers-account-address branch from 7931099 to 3b85b1a Compare December 11, 2024 14:53
Copy link

sonarcloud bot commented Dec 11, 2024

Copy link
Member

@quiet-node quiet-node left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! However, additional tests are still needed. Also a batch of unit tests is required in the precheck.spec.ts file to functionally test the method.


if (verifyAccount !== null && verifyAccount.receiver_sig_required === true) {
throw predefined.INTERNAL_ERROR("Receiver's signature is required.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait this block only executes when tx.to is not null; therefore, it is still possible for the mirror node to return a null result if tx.to is not found on the network. I'd suggest instead of checking if (verifyAccount !== null && verifyAccount.receiver_sig_required === true) for the sig required, we can pull the verifyAccount !== null out and add a new block to check the validity of the verifyAccount. If it's null then throw RESOURCE_NOT_FOUND like how we did with the tx.from.

Comment on lines +1597 to +1635
it('should fail "eth_sendRawTransaction" if receiver\'s account has receiver_sig_required enabled', async function () {
const newPrivateKey = PrivateKey.generateED25519();
const newAccount = await new AccountCreateTransaction()
.setKey(newPrivateKey.publicKey)
.setInitialBalance(100)
.setReceiverSignatureRequired(true)
.freezeWith(servicesNode.client)
.sign(newPrivateKey);

const transaction = await newAccount.execute(servicesNode.client);
const receipt = await transaction.getReceipt(servicesNode.client);

if (!receipt.accountId) {
throw new Error('Failed to create new account - accountId is null');
}

const toAddress = Utils.idToEvmAddress(receipt.accountId.toString());
const tx = {
nonce: await accounts[0].wallet.getNonce(),
chainId: CHAIN_ID,
to: toAddress,
from: accounts[0].address,
value: '0x2E90EDD000',
gasLimit: defaultGasLimit,
accessList: [],
maxPriorityFeePerGas: defaultGasPrice,
maxFeePerGas: defaultGasPrice,
};

const signedTx = await accounts[0].wallet.signTransaction(tx);
await new Promise((r) => setTimeout(r, 3000));

const error = predefined.RECEIVER_SIGNATURE_REQUIRED;

await Assertions.assertPredefinedRpcError(error, sendRawTransaction, false, relay, [
signedTx,
requestDetails,
]);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great test! Let's add another test to ensure it works fine when receiver.to has receiver_sig_required disabled.

Additionally, if we decide to throw a RESOURCE_NOT_FOUND error for tx.to, we should include another test that uses an address not present in the system to verify that it blocks the request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add prechecks to the sendRawTransaction method to verify the validity of the receiver's account address.
3 participants